/**
 * @file lcd_drive.h
 * @author cangyu (sky.kirto@qq.com)
 * @brief
 * @version 0.1
 * @date 2024-09-02
 *
 * @copyright Copyright (c) 2024, CorAL. All rights reserved.
 *
 */

#ifndef __LCD_DRIVE_H__
#define __LCD_DRIVE_H__

/* ==================== [Includes] ========================================== */

#include "xf_utils.h"

#ifdef __cplusplus
extern "C" {
#endif

/* ==================== [Defines] =========================================== */

/* ==================== [Typedefs] ========================================== */

typedef void *lcd_t;

typedef xf_err_t (*lcd_write_cmd_t)(uint8_t *cmd, uint32_t len);
typedef xf_err_t (*lcd_write_data_t)(uint8_t *data, uint32_t len);
typedef xf_err_t (*lcd_reset_t)(void);
typedef xf_err_t (*lcd_backlight_t)(bool is_on);

typedef struct _lcd_drive_in_t {
    lcd_write_cmd_t write_cmd;
    lcd_write_data_t write_data;
    lcd_reset_t reset;
    lcd_backlight_t backlight;
} lcd_drive_in_t;

/**
 * @brief Define all screen direction
 *
 */
typedef enum _lcd_scr_dir_t {
    /* @---> X
       |
       Y
    */
    SCR_DIR_LRTB,   /**< From left to right then from top to bottom, this consider as the original direction of the screen */

    /*  Y
        |
        @---> X
    */
    SCR_DIR_LRBT,   /**< From left to right then from bottom to top */

    /* X <---@
             |
             Y
    */
    SCR_DIR_RLTB,   /**< From right to left then from top to bottom */

    /*       Y
             |
       X <---@
    */
    SCR_DIR_RLBT,   /**< From right to left then from bottom to top */

    /* @---> Y
       |
       X
    */
    SCR_DIR_TBLR,   /**< From top to bottom then from left to right */

    /*  X
        |
        @---> Y
    */
    SCR_DIR_BTLR,   /**< From bottom to top then from left to right */

    /* Y <---@
             |
             X
    */
    SCR_DIR_TBRL,   /**< From top to bottom then from right to left */

    /*       X
             |
       Y <---@
    */
    SCR_DIR_BTRL,   /**< From bottom to top then from right to left */

    SCR_DIR_MAX,

    /* Another way to represent rotation with 3 bit*/
    SCR_MIRROR_X = 0x40, /**< Mirror X-axis */
    SCR_MIRROR_Y = 0x20, /**< Mirror Y-axis */
    SCR_SWAP_XY  = 0x80, /**< Swap XY axis */
} lcd_scr_dir_t;

typedef enum _lcd_scr_controller_t {
    SCR_CONTROLLER_NONE = -1,
#define LCD_REG_ENUM
#include "lcd_drive_rule.h"
    SCR_CONTROLLER_MAX,
} lcd_scr_controller_t;


/* ==================== [Global Prototypes] ================================= */

lcd_t *lcd_drive_create(const lcd_drive_in_t *in);
xf_err_t lcd_drive_init(lcd_t self, lcd_scr_controller_t controller, uint16_t width, uint16_t height);
xf_err_t lcd_drive_draw_bitmap(lcd_t self, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *bitmap);
xf_err_t lcd_set_rotation(lcd_t self, lcd_scr_dir_t dir);
xf_err_t lcd_set_invert(lcd_t self, bool is_invert);

/* ==================== [Macros] ============================================ */

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif // __LCD_DRIVE_H__
